import AiUser from '../../model/AiUser'
import ApiError from '../../error/ApiError'
import ApiErrorNames from '../../error/ApiErrorNames'
import redis from '../../dbHelper/redis'
import { geneRandomCode } from '../../utils/toole'
import moment from 'moment'
import jwt from 'jsonwebtoken'
import { jwtConfig } from '../../config/index'
import Shop from '../../model/shop'
import { aiSendUserSorce, aiSendShopSorce } from '../../config/index'
import Orders from '../../model/orders'

import { rightsInfo } from '../../api/token'

const tencentcloud = require("tencentcloud-sdk-nodejs")
// console.log('tencentcloud', tencentcloud)
const smsClient = tencentcloud.sms.v20210111.Client
const client = new smsClient({
    credential: {
        /* 必填：腾讯云账户密钥对secretId，secretKey。
         * 这里采用的是从环境变量读取的方式，需要在环境变量中先设置这两个值。
         * 您也可以直接在代码中写死密钥对，但是小心不要将代码复制、上传或者分享给他人，
         * 以免泄露密钥对危及您的财产安全。
         * SecretId、SecretKey 查询: https://console.cloud.tencent.com/cam/capi */
        secretId: process.env.TENCENTCLOUD_SECRET_ID,
        secretKey: process.env.TENCENTCLOUD_SECRET_KEY,
    },
    /* 必填：地域信息，可以直接填写字符串ap-guangzhou，支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8 */
    region: "ap-nanjing",
    /* 非必填:
     * 客户端配置对象，可以指定超时时间等配置 */
    profile: {
        /* SDK默认用TC3-HMAC-SHA256进行签名，非必要请不要修改这个字段 */
        signMethod: "HmacSHA256",
        httpProfile: {
            /* SDK默认使用POST方法。
             * 如果您一定要使用GET方法，可以在这里设置。GET方法无法处理一些较大的请求 */
            reqMethod: "POST",
            /* SDK有默认的超时时间，非必要请不要进行调整
             * 如有需要请在代码中查阅以获取最新的默认值 */
            reqTimeout: 30,
            /**
             * 指定接入地域域名，默认就近地域接入域名为 sms.tencentcloudapi.com ，也支持指定地域域名访问，例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com
             */
            endpoint: "sms.tencentcloudapi.com"
        },
    },
})



let codeOutTime = 5
let refoCode = 1
class AiUSersControlle {
    static async code(ctx) {
        // 获取列表全部数据
        const { phone } = ctx.request.query || {}
        if (!phone) {
            throw new ApiError(ApiErrorNames.nogetText('phone'))
        }

        let reg = /^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/
        if (!reg.test(phone)) {
            throw new ApiError(ApiErrorNames.PHONE_FORMAT_ERROR)
        }
        const codeData = await redis.get('code_' + phone)
        const params = {
            /* 短信应用ID: 短信SmsSdkAppId在 [短信控制台] 添加应用后生成的实际SmsSdkAppId，示例如1400006666 */
            // 应用 ID 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看
            SmsSdkAppId: process.env.SMS_SDK_APP_ID,
            /* 短信签名内容: 使用 UTF-8 编码，必须填写已审核通过的签名 */
            // 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-sign) 的签名管理查看
            SignName: process.env.SIGN_NAME,
            /* 模板 ID: 必须填写已审核通过的模板 ID */
            // 模板 ID 可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-template) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-template) 的正文模板管理查看
            TemplateId: process.env.TEMPLATE_ID,
            /* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致，若无模板参数，则设置为空 */
            // TemplateParamSet: [code, codeOutTime],
            /* 下发手机号码，采用 e.164 标准，+[国家或地区码][手机号]
             * 示例如：+8613711112222， 其中前面有一个+号 ，86为国家码，13711112222为手机号，最多不要超过200个手机号*/
            PhoneNumberSet: [`+86${phone}`],
            /* 用户的 session 内容（无需要可忽略）: 可以携带用户侧 ID 等上下文信息，server 会原样返回 */
            SessionContext: "",
            /* 短信码号扩展号（无需要可忽略）: 默认未开通，如需开通请联系 [腾讯云短信小助手] */
            ExtendCode: "",
            /* 国内短信无需填写该项；国际/港澳台短信已申请独立 SenderId 需要填写该字段，默认使用公共 SenderId，无需填写该字段。注：月度使用量达到指定量级可申请独立 SenderId 使用，详情请联系 [腾讯云短信小助手](https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81)。 */
            SenderId: "",
        }
        if (codeData) {

            const codeDataJson = JSON.parse(codeData)
            if (moment().isBefore(moment(codeDataJson.expireTime))) {
                if (moment(codeDataJson.createTime).add(refoCode, 'minutes').isAfter(moment())) {
                    // 发送频繁
                    throw new ApiError(ApiErrorNames.SEND_CODE_TOO_FREQUENT)
                }
                // 重新写发送时间
                const addCodeData = {
                    code: codeDataJson.use ? geneRandomCode(6) : codeDataJson.code,
                    expireTime: moment().add(codeOutTime, 'minutes').format('YYYY-MM-DD HH:mm:ss'), // moment().add(10, 'seconds').format('YYYY-MM-DD HH:mm:ss')
                    createTime: moment().format('YYYY-MM-DD HH:mm:ss'),
                    // 是否使用
                    use: false
                }
                params.TemplateParamSet = [addCodeData.code, codeOutTime]
                const sendSms = await client.SendSms(params)


                console.log('sendSms', sendSms)
                if (sendSms.SendStatusSet[0].Code == 'Ok') {
                    const setredusData = await redis.set('code_' + phone, JSON.stringify(addCodeData))
                    return ctx.body = codeDataJson.use ? '重新发送新验证码' + addCodeData.code : '未过期已经重新发送' + setredusData
                } else {
                    throw new ApiError(ApiErrorNames.sendSmsErr({
                        code: 2500,
                        message: sendSms.SendStatusSet
                    }))
                }
                // 这里发送验证码
            }
        }
        // 检查上面的验证码是否过期
        const code = geneRandomCode(6)
        const addCodeData = {
            code,
            expireTime: moment().add(codeOutTime, 'minutes').format('YYYY-MM-DD HH:mm:ss'), // moment().add(10, 'seconds').format('YYYY-MM-DD HH:mm:ss')
            createTime: moment().format('YYYY-MM-DD HH:mm:ss'),
            // 是否使用
            use: false
        }
        // 这里发送验证码
        params.TemplateParamSet = [code, codeOutTime]
        const sendSms = await client.SendSms(params)
        if (sendSms.SendStatusSet[0].Code == 'Ok') {
            const setredusData = await redis.set('code_' + phone, JSON.stringify(addCodeData))
            // console.log('sendSms', sendSms, setredusData)
            return ctx.body = '已发送 ' + setredusData
        } else {
            throw new ApiError(ApiErrorNames.sendSmsErr({
                code: 2500,
                message: sendSms.SendStatusSet
                // content: sendSms.SendStatusSet
            }))
        }


    }
    static async creted(ctx) {
        const {
            phone = '',
            code = '',
        } = ctx.request.body || {}
        if (!phone || !code) {
            // 缺少必要参数
            throw new ApiError(ApiErrorNames.NoParamsData)
        }
        const codeData = await redis.get('code_' + phone)
        // console.log('codeData', codeData)
        if (codeData) {
            const codeDataJson = JSON.parse(codeData)
            if (codeDataJson.code == code) {
                if (codeDataJson.use) {
                    // 验证码已使用
                    throw new ApiError(ApiErrorNames.CODE_ERROR_USED)
                }
                if (moment().isAfter(moment(codeDataJson.expireTime))) {
                    // 验证码过期
                    throw new ApiError(ApiErrorNames.CODE_ERROR_TIMEOUT)
                }
                const AiUserToken = await addAiUserOrLogin(phone)
                ctx.body = AiUserToken
                codeDataJson.use = true
                await redis.set('code_' + phone, JSON.stringify(codeDataJson))
                // 验证码正确
                // 这里登陆或者注册
            } else {
                // 验证码错误
                throw new ApiError(ApiErrorNames.CODE_ERROR)
            }
        } else {
            // 验证码错误
            throw new ApiError(ApiErrorNames.CODE_ERROR)
        }

    }
    static async bindShop(ctx) {
        ctx.verifyParams({
            shop_id: { type: 'string', required: true },
        })
        const { shop_id } = ctx.request.query || {}
        const getShopData = await Shop.findOne({ shop_id })
        console.log('bindShop', getShopData.aiUserId)
        // const rightsInfoData = await rightsInfo({
        //     access_token: getShopData.access_token,
        // })
        // console.log('rightsInfoData*****', rightsInfoData)
        if (!getShopData) {
            // 店铺不存在
            throw new ApiError(ApiErrorNames.SHOP_ID_NOT_EXIST)
        }
        // console.log('ctx.request.header.jwtuserinfo', ctx.request.header.jwtuserinfo)
        const aiUserData = JSON.parse(ctx.request.header.jwtuserinfo)
        // await AiUser.updateOne({ _id: aiUserData._id }, { $inc: { remainSendScore: -100000 }, $min: { remainSendScore: 0 } })
        // return ctx.body = 123
        // 店铺已绑定 同一个用户
        if (getShopData.aiUserId) { // *******************************************************
            // console.log('ctx.request.header.jwtuserinfo', aiUserData)
            if (getShopData.aiUserId == aiUserData._id) {
                // 店铺已绑定 同一个用户
                throw new ApiError(ApiErrorNames.SHOP_ID_BINDED)
            }
            const aiUserInfo = await AiUser.findById(getShopData.aiUserId)
            console.log('aiUserInfo', aiUserInfo)
            // 店铺已绑定 不同用户
            throw new ApiError(ApiErrorNames.SHOP_ID_BINDED_OTHER(aiUserInfo.phone))
        }
        if (getShopData.isBuy == 1 || getShopData.isBuy == 2) {
            // 有订购的情况下 查询订单的什么版本
            // 订购试用版后面再处理
            const getShopOrderData = await Orders.findOne({ shop_id }).sort({ createTime: -1 })
            // console.log('该店铺最后一个的订单', getShopOrderData)
            if (getShopOrderData.isRefund == 0 && !getShopOrderData.isGive) {
                // 这个订单没有退款 可以送
                const giveData = aiSendShopSorce.find((item) => item.spec_value == getShopOrderData.push_sku_info.spec_value).chr.find((item) => item.title == getShopOrderData.push_sku_info.title)
                if (giveData) {
                    // 给用户送积分
                    await Shop.updateOne({ shop_id }, {
                        $inc: { aiRemainScore: giveData.give_num }
                    })
                    getShopOrderData.isGive = 1
                    getShopOrderData.save()
                }
            }
        }
        // return ctx.body = '6666'
        // 店铺未绑定
        // 这里查询用户当前插件付费情况
        const updateShopData = await Shop.updateOne({ shop_id }, {
            aiUserId: aiUserData._id,
            bindAiuserTime: moment().format('YYYY-MM-DD HH:mm:ss'),
        })
        // console.log('updateShopData', updateShopData)
        // console.log('bindShop', '需要shopID', ctx.)
        ctx.body = shop_id
    }
    static async userinfo(ctx) {
        const aiUserData = JSON.parse(ctx.request.header.jwtuserinfo)
        const getUserInfoData = await AiUser.findOne({ _id: aiUserData._id }, { password: 0 })
        ctx.body = getUserInfoData
    }
    static async bindinfo(ctx) {
        const { shop_id } = ctx.request.query || {}
        const aiUserData = JSON.parse(ctx.request.header.jwtuserinfo)
        const shearData = {
            aiUserId: aiUserData._id,
        }
        if (shop_id) {
            shearData.shop_id = shop_id
        }
        const getShopData = await Shop.find(shearData)
        const total = await Shop.countDocuments(shearData)
        ctx.body = {
            list: getShopData || [],
            total
        }
    }
    static async unbindShop(ctx) {
        console.log('ctx.params', ctx.params)
        const { shop_id } = ctx.params || {}
        if (!shop_id) {
            throw new ApiError(ApiErrorNames.SHOP_ID_NOT_EXIST)
        }
        const aiUserData = JSON.parse(ctx.request.header.jwtuserinfo)
        const getBindShopData = await Shop.findOne({ shop_id, aiUserId: aiUserData._id })
        if (!getBindShopData) {
            // 店铺未绑定
            throw new ApiError(ApiErrorNames.SHOP_ID_NOT_EXIST)
        }
        const updateShopData = await Shop.updateOne({ shop_id }, { aiUserId: null })
        console.log('shop_id', shop_id)
        ctx.body = shop_id
    }
    static async refreshLogin(ctx) {
        // console.log('123465', ctx.request.body)
        const { refresh_token } = ctx.request.body || {}
        if (!refresh_token) {
            // ctx.body = '缺少refresh_token'
            throw new ApiError(ApiErrorNames.selectInDengtData('缺少refresh_token'))

        }
        if (ctx.header.authorization) {
            const jwtstr = ctx.header.authorization.split('Bearer ')[1]
            try {
                const jwtdata = jwt.verify(jwtstr, jwtConfig.secret)
                const aiUserData = await addAiUserOrLogin(jwtdata.phone)
                ctx.body = aiUserData
            } catch (error) {
                if (error.name == 'TokenExpiredError') {
                    try {
                        const jwtrefreshdata = jwt.verify(refresh_token, jwtConfig.refresh_secret)
                        const aiUserData = await addAiUserOrLogin(jwtrefreshdata.phone)
                        ctx.body = aiUserData
                    } catch (error) {
                        throw new ApiError(ApiErrorNames.REFOTOEK_ERR)
                    }
                    return
                }
                throw new ApiError(ApiErrorNames.selectInDengtData('无效token'))
            }
            return
        }
        throw new ApiError(ApiErrorNames.selectInDengtData('缺少原token'))
    }
}

export default AiUSersControlle

async function addAiUserOrLogin(phone) {
    const getUserData = await AiUser.findOne({ phone })
    // console.log('getUserData', getUserData._doc)
    let token
    let refresh_token
    if (getUserData) {
        // 用户已存在
        // 这里登陆
        token = jwt.sign({ ...getUserData._doc, for: 'ai' }, jwtConfig.secret, {
            expiresIn: '30d',
        })
        refresh_token = jwt.sign({ ...getUserData._doc, for: 'ai' }, jwtConfig.refresh_secret, {
            expiresIn: '120d',
        })
        return {
            token,
            type: 'login',
            refresh_token
        }
    }
    const getUserFoter = await AiUser.create({
        phone: phone,
        ...aiSendUserSorce
    })
    // console.log('getUserFoter', getUserFoter._doc)
    token = jwt.sign({ ...getUserFoter._doc, for: 'ai' }, jwtConfig.secret, {
        expiresIn: '30d',
    })
    refresh_token = jwt.sign({ ...getUserFoter._doc, for: 'ai' }, jwtConfig.refresh_secret, {
        expiresIn: '120d',
    })
    return {
        token,
        type: 'register',
        refresh_token
    }
}